import React, { useEffect, useState } from "react";
import axios from "axios";
import * as d3 from "d3";
import store from "../../redux/store";
import { totalDataAction } from "../../redux/actions/totalData";
const BoxChart = () => {
  const [dataTree, setDataTree] = useState({
    name: "",
    version: "",
    children: [],
  });
  const [allDataTree, setAll] = useState([]);
  useEffect(() => {
    getTreeMap({ filename: undefined, depth: 3 });
  }, []);

  const drawTreeMap = () => {
    const margin = { top: 10, right: 10, bottom: 10, left: 10 },
      width = 1200 - margin.left - margin.right,
      height = 900 - margin.top - margin.bottom;
    const colorScale = d3.scaleOrdinal(d3.schemeSet3);
    // 绘制 treemap 的代码...
    d3.select("#my_dataviz").html("");
    const svg = d3
      .select("#my_dataviz")
      .append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", `translate(${margin.left},${margin.right})`);

    // 创建层次结构
    const root = d3.hierarchy(dataTree).sum((d) => {
      return 1;
    });

    d3
      .treemap()
      .size([width, height])
      .round(true)
      // .tile(d3.treemapBinary)
      .paddingTop(30)
      .paddingRight(18)
      .paddingBottom(15)
      .paddingLeft(10)(root);

    //   透明度
    const opacity = d3.scaleLinear().domain([0, 10]).range([0.8, 1]);
    const minRectWidth = 10;
    const minRectHeight = 50;
    svg
      .selectAll("rect")
      .data(root.descendants())
      .join("rect")
      .attr("x", (d) => d.x0)
      .attr("y", (d) => d.y0)
      .attr("width", (d) => Math.max(d.x1 - d.x0, minRectWidth)) // 检查并设置最小宽度
      .attr("height", (d) => Math.max(d.y1 - d.y0, minRectHeight)) // 检查并设置最小高度
      .attr("fill", (d, i) => {
        if (!d.parent) return colorScale(i);
        if (!d.children) return colorScale(d.data.name);
        return colorScale(d.parent.data.name);
      })
      .style("stroke", "black")
      .style("opacity", (d) => {
        return opacity(d.value);
      })
      .on("click", (event, d) => {
        const name = d.data.name;
        const clickedData = {
          filename: name,
          depth: 3,
        };
        getTreeMap(clickedData);
      });

    svg
      .selectAll("text")
      .data(root.descendants())
      .enter()
      .append("text")
      .attr("x", (d) => d.x0 + 5)
      .attr("y", (d) => d.y0 + 21)
      .attr("fill", "black")
      .each(function (d) {
        let text = d3.select(this);
        let name = d.data.name;
        let version = d.data.version;
        if (d.children) {
          text.text(name + " version:" + version);
        } else {
          let nameFontSize = 20 - d.depth * 2;
          let versionFontSize = 10;
          if (nameFontSize < 10) {
            nameFontSize = 10;
          }
          if (versionFontSize < 10) {
            versionFontSize = 10;
          }
          let nameTspan = text
            .append("tspan")
            .text(name)
            .attr("x", d.x0 + 5)
            .attr("font-size", `${nameFontSize}px`);
          let versionTspan = text
            .append("tspan")
            .text("version:" + version)
            .attr("x", d.x0 + 5)
            .attr("dy", "1.2em")
            .attr("font-size", `${versionFontSize}px`);
          if (d.x1 - d.x0 < nameFontSize * name.length) {
            wrapText(nameTspan, name, nameFontSize, d.x1 - d.x0);
          }
          if (d.x1 - d.x0 < versionFontSize * version.length) {
            wrapText(versionTspan, version, versionFontSize, d.x1 - d.x0);
          }
        }
      });

    function wrapText(tspan, text, fontSize, width) {
      tspan.text(null);
      let words = text.split("");
      let line = [];
      let lineNumber = 0;
      let dy = fontSize;
      let word;
      while ((word = words.shift())) {
        line.push(word);
        tspan.text(line.join(""));
        if (tspan.node().getComputedTextLength() > width) {
          line.pop();
          tspan.text(line.join(""));
          line = [word];
          tspan = tspan
            .append("tspan")
            .attr("x", tspan.attr("x"))
            .attr("dy", ++lineNumber * dy + "px")
            .text(word);
        }
      }
    }
    // 添加返回按钮的事件处理函数
    const handleGoBack = () => {
      if (allDataTree.length - 2 >= 0) {
        const parentData = allDataTree[allDataTree.length - 2];
        let tempAllDataTree = allDataTree;
        tempAllDataTree.pop();
        setDataTree(parentData);
        setAll(tempAllDataTree);
        drawTreeMap();
      }
      console.log("点击返回后的数据", allDataTree);
    };

    // 在 SVG 容器中添加返回按钮
    d3.select("#my_dataviz")
      .append("button")
      .text("返回上一级")
      .style("position", "absolute")
      .style("margin-top", "10px")
      .style("background", "#c2a8ff")
      .style("border-radius", "5px")
      .on("click", handleGoBack);
  };

  const getTreeMap = async (data) => {
    try {
      console.log(data, "box发送请求的参数");
      const response = await axios.get("http://localhost:3000/getTreeMapData", {
        params: data,
      });
      const getTreedata = response.data;
      console.log(getTreedata, "treemap数据");
      store.dispatch(totalDataAction(getTreedata));
      if (allDataTree[allDataTree.length - 1] !== getTreedata) {
        setAll([...allDataTree, getTreedata]);
      }
      setDataTree(getTreedata);
    } catch (error) {
      // 处理错误
      console.error(error);
    }
  };
  console.log(dataTree, allDataTree, "box发送请求得到的参数");
  drawTreeMap();

  return (
    <div id="my_dataviz" className="box_container">
      {/* SVG 容器 */}
    </div>
  );
};

export default BoxChart;
